package com.example.controller;

import com.example.entity.RestBean;
import com.example.entity.dto.Interact;
import com.example.entity.vo.request.AddCommentVO;
import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.*;
import com.example.service.TopicService;
import com.example.service.WeatherService;
import com.example.utils.Const;
import com.example.utils.ControllerUtils;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Pattern;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * 作者:xuSen
 * 日期:2025/4/27 8:35
 * 该控制器类负责处理论坛相关的各类请求，涵盖天气信息获取、主题管理、用户交互、评论管理等功能。
 */
@RestController
@RequestMapping("/api/forum")
public class ForumController {

    // 注入天气服务，用于获取指定经纬度的天气信息
    @Resource
    private WeatherService weatherService;
    // 注入主题服务，用于处理论坛主题的相关操作
    @Resource
    private TopicService topicService;
    // 注入控制器工具类，用于处理消息响应
    @Resource
    private ControllerUtils utils;

    /**
     * 获取天气信息
     * 根据传入的经度和纬度获取对应的天气信息，确保请求参数非空。
     *
     * @param longitude 经度，用于定位地理位置，不可为空
     * @param latitude  纬度，用于定位地理位置，不可为空
     * @return RestBean<WeatherVO> 返回封装了天气信息的RestBean对象，操作成功时包含天气信息，失败时包含错误信息
     */
    @GetMapping("/weather")
    public RestBean<WeatherVO> weather(Double longitude, Double latitude) {
        // 检查经度和纬度参数是否存在，如果不存在则返回错误信息
        if (longitude == null || latitude == null) {
            return RestBean.failure(400, "经度和纬度参数不能为空");
        }
        // 调用weatherService的fetchWeather方法获取天气信息
        WeatherVO weatherVO = weatherService.fetchWeather(longitude, latitude);
        // 检查获取的天气信息是否为空，如果为空则返回错误信息
        if (weatherVO == null) {
            return RestBean.failure(500, "获取天气信息失败");
        }
        // 返回成功获取的天气信息
        return RestBean.success(weatherVO);
    }

    /**
     * 获取主题类型列表
     * 通过GET请求访问/types端点，返回所有主题类型的视图对象列表。
     * 使用RestBean封装返回结果，确保响应格式的一致性和扩展性。
     *
     * @return 包含主题类型视图对象列表的RestBean对象，操作成功时包含主题类型列表，失败时包含错误信息
     */
    @GetMapping("/types")
    public RestBean<List<TopicTypeVO>> listTypes() {
        // 调用服务层方法获取主题类型列表，并转换为视图对象列表
        // 使用Java Stream API对每个主题类型进行映射转换，并收集到一个新的列表中
        // 通过RestBean.success方法封装成功的响应结果
        return RestBean.success(topicService.listTypes().stream().map(type -> type.asViewObject(TopicTypeVO.class)).toList());
    }

    /**
     * 创建新主题的接口
     * 该方法通过POST请求接收主题创建信息，并处理主题创建逻辑。
     *
     * @param topicCreateVO 主题创建的详细信息，包括主题名称、描述等，使用@Valid注解确保数据合法性
     * @param id            用户ID，用于标识主题的创建者，通过@RequestAttribute从请求中获取
     * @return 返回操作结果的RestBean对象，包含操作是否成功的信息
     */
    @PostMapping("/create-topic")
    public RestBean<Void> createTopic(@Valid @RequestBody TopicCreateVO topicCreateVO,
                                      @RequestAttribute(Const.ATTR_USER_ID) int id) {
        return utils.messageHandle(() -> topicService.createTopic(topicCreateVO, id));
    }
    /**
     * 删除主题
     *
     * 此方法允许用户通过GET请求删除一个主题它要求提供主题ID（tid）和用户ID（uid），
     * 其中主题ID必须大于等于0用户ID通过RequestAttribute从请求中获取，用于标识执行删除操作的用户
     *
     * @param tid 主题ID，必须大于等于0
     * @param uid 用户ID，用于标识执行删除操作的用户
     * @return RestBean<Void> 返回一个表示操作结果的RestBean对象，不含具体数据
     */
    @GetMapping("/delete-topic")
    public RestBean<Void> deleteTopic(@RequestParam @Min(0) int tid,
                                      @RequestAttribute(Const.ATTR_USER_ID) int uid) {
        topicService.deleteTopic(tid, uid);
        return RestBean.success();
    }

    /**
     * 获取话题列表
     * 根据传入的页码和类型筛选并返回话题预览信息列表。
     *
     * @param page 页码，从0开始，用于分页查询，使用@Min(0)注解确保页码为非负整数
     * @param type 类型，从0开始，用于筛选话题类型，使用@Min(0)注解确保类型为非负整数
     * @return 包含话题预览信息列表的RestBean对象，操作成功时包含话题列表，失败时包含错误信息
     */
    @GetMapping("/list-topic")
    public RestBean<List<TopicPreviewVO>> listTopic(@RequestParam @Min(0) int page,
                                                    @RequestParam @Min(0) int type) {
        // 调用服务层方法，按页码和类型查询话题列表，并返回成功结果
        return RestBean.success(topicService.listTopicByPage(page + 1, type));
    }

    /**
     * 获取热门话题列表
     * 该方法通过GET请求映射到"/top-topic"，用于获取系统中热门话题的列表。
     * 它调用了TopicService中的listTopTopic方法来获取数据，并将结果封装在RestBean中返回。
     *
     * @return RestBean<List<TopicTopVO>> 返回一个包含热门话题列表的RestBean对象，操作成功时包含热门话题列表，失败时包含错误信息
     */
    @GetMapping("/top-topic")
    public RestBean<List<TopicTopVO>> topTopic() {
        return RestBean.success(topicService.listTopTopic());
    }

    /**
     * 根据主题ID获取主题详情
     *
     * @param tid 主题ID，必须为非负整数，使用@Min(0)注解确保ID合法性
     * @param uid 用户ID，通过@RequestAttribute从请求中获取，用于标识当前用户
     * @return 返回包含主题详情的RestBean对象，操作成功时包含主题详情，失败时包含错误信息
     */
    @GetMapping("/topic")
    public RestBean<TopicDetailsVO> topic(@RequestParam @Min(0) int tid,
                                          @RequestAttribute(Const.ATTR_USER_ID) int uid) {
        return RestBean.success(topicService.getTopic(tid, uid));
    }

    /**
     * 处理用户与主题的交互请求，如点赞、收藏等
     *
     * @param tid   主题ID，必须为非负整数，使用@Min(0)注解确保ID合法性
     * @param type  交互类型，仅限于"like"、"dislike"、"collect"、"report"之一，使用@Pattern注解进行限制
     * @param state 交互状态，表示用户是否进行该交互操作
     * @param id    用户ID，通过@RequestAttribute从请求中获取，用于标识当前用户
     * @return 返回表示操作结果的RestBean对象，操作成功时表示交互操作已处理，失败时包含错误信息
     */
    @GetMapping("/interact")
    public RestBean<Void> interact(@RequestParam @Min(0) int tid,
                                   @RequestParam @Pattern(regexp = ("like|dislike|collect|report")) String type,
                                   @RequestParam boolean state,
                                   @RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 创建一个Interact对象，封装主题ID、用户ID、当前日期和交互类型
        // 调用topicService的interact方法，根据当前交互状态更新数据库
        topicService.interact(new Interact(tid, id, new Date(), type), state);
        // 返回一个表示操作成功的RestBean对象
        return RestBean.success();
    }

    /**
     * 获取用户收藏的主题列表
     *
     * @param id 用户ID，通过@RequestAttribute从请求中获取，用于标识当前用户
     * @return 返回包含用户收藏主题预览信息列表的RestBean对象，操作成功时包含收藏主题列表，失败时包含错误信息
     */
    @GetMapping("/collects")
    public RestBean<List<TopicPreviewVO>> collects(@RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 调用topicService的getCollects方法获取用户收藏的主题列表
        // 将每个主题转换为视图对象，并收集到一个新的列表中
        // 返回一个包含收藏主题视图对象的RestBean对象
        return RestBean.success(topicService.ListTopicCollects(id));
    }

    /**
     * 更新主题信息
     *
     * @param topicUpdateVO 主题更新信息，包括主题ID、类型、标题和内容，使用@Valid注解确保数据合法性
     * @param id            用户ID，通过@RequestAttribute从请求中获取，用于标识操作者
     * @return 返回表示操作结果的RestBean对象，操作成功时表示主题信息已更新，失败时包含错误信息
     */
    @PostMapping("update-topic")
    public RestBean<Void> updateTopic(@Valid @RequestBody TopicUpdateVO topicUpdateVO,
                                      @RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 调用topicService的updateTopic方法更新主题信息
        // 返回一个表示操作成功的RestBean对象
        return utils.messageHandle(() -> topicService.updateTopic(id, topicUpdateVO));
    }

    /**
     * 添加评论
     *
     * @param addCommentVO 评论创建信息，包括评论内容、关联的主题ID和评论的父级ID，使用@Valid注解确保数据合法性
     * @param id           用户ID，通过@RequestAttribute从请求中获取，用于标识评论者
     * @return 返回表示操作结果的RestBean对象，操作成功时表示评论已添加，失败时包含错误信息
     */
    @PostMapping("/add-comment")
    public RestBean<Void> addComment(@Valid @RequestBody AddCommentVO addCommentVO,
                                     @RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 调用topicService的addComment方法添加评论
        // 返回一个表示操作成功的RestBean对象
        return utils.messageHandle(() -> topicService.addComment(addCommentVO, id));
    }

    /**
     * 获取指定主题的评论列表
     *
     * @param tid  主题ID，必须为非负整数，使用@Min(0)注解确保ID合法性
     * @param page 页码，从1开始，用于分页查询，使用@Min(0)注解确保页码为非负整数
     * @return 返回包含评论视图对象列表的RestBean对象，操作成功时包含评论列表，失败时包含错误信息
     */
    @GetMapping("/comments")
    public RestBean<List<CommentVO>> comments(@RequestParam @Min(0) int tid,
                                              @RequestParam @Min(0) int page) {
        // 调用topicService的getComments方法获取评论列表
        // 将每个评论转换为视图对象，并收集到一个新的列表中
        // 返回一个包含评论视图对象的RestBean对象
        return RestBean.success(topicService.getComments(tid, page + 1));
    }

    /**
     * 删除评论
     *
     * @param cid 评论ID，必须为非负整数，使用@Min(0)注解确保ID合法性
     * @param uid 用户ID，通过@RequestAttribute从请求中获取，用于标识操作者
     * @return 返回表示操作结果的RestBean对象，操作成功时表示评论已删除，失败时包含错误信息
     */
    @GetMapping("/delete-comment")
    public RestBean<Void> deleteComment(@RequestParam @Min(0) int cid,
                                        @RequestAttribute(Const.ATTR_USER_ID) int uid) {
        // 调用topicService的deleteComment方法删除评论
        topicService.deleteComment(cid, uid);
        return RestBean.success();
    }
}